package com.hushan.elevator.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.hushan.elevator.dao.*;
import com.hushan.elevator.dto.RiskRecordDto;
import com.hushan.elevator.model.*;
import com.hushan.elevator.service.RiskRecordService;
import com.hushan.elevator.vo.RiskSearchVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class RiskRecordServiceImpl implements RiskRecordService {

    private final RiskRecordRepository riskRecordDao;
    private final RiskRecordElevStatusRepository elevStatusDao;
    private final DeviceTypeRepository deviceTypeDao;
    private final DeviceInfoRepository deviceInfoDao;
    private final RiskHandleRepository riskHandleDao;

    @Autowired
    public RiskRecordServiceImpl(RiskRecordRepository riskRecordDao, RiskRecordElevStatusRepository elevStatusDao, DeviceTypeRepository deviceTypeDao, DeviceInfoRepository deviceInfoDao, RiskHandleRepository riskHandleDao) {
        this.riskRecordDao = riskRecordDao;
        this.elevStatusDao = elevStatusDao;
        this.deviceTypeDao = deviceTypeDao;
        this.deviceInfoDao = deviceInfoDao;
        this.riskHandleDao = riskHandleDao;
    }


    @Override
    public RiskRecord findRiskRecordById(Integer id) {
        return riskRecordDao.findById(id).orElse(null);
    }

    @Override
    public void updateRiskRecord(RiskRecord riskRecord) {
        riskRecordDao.save(riskRecord);
    }

    @Override
    public void deleteRiskRecord(Integer id) {
        riskRecordDao.deleteById(id);
    }

    @Override
    public void addRiskRecord(RiskRecord risk) {
        riskRecordDao.save(risk);
    }

    @Override
    public RiskRecordDto findRiskRecordDetail(Integer recordId) {
        Page<Object[]> risk = riskRecordDao.findRisk(recordId, null, null, null, null, null, null, null);
        if (risk.isEmpty()) {
            return null;
        }
        return convertRiskRecordDto(risk.stream().toList()).get(0);
    }


    @Override
    public void addRiskRecordElevStatus(RiskRecordElevStatus elevStatus) {
        elevStatusDao.save(elevStatus);
    }

    @Override
    public RiskRecordElevStatus findElevStatus(int id) {
        return elevStatusDao.findById(id).orElse(null);
    }

    @Override
    public DeviceInfo findDeviceByRisk(int riskId) throws RuntimeException {
        RiskRecord record = riskRecordDao.findById(riskId).orElse(null);
        if (record == null) {
            throw new RuntimeException("risk not exist");
        }
        return findDeviceByRisk(record);
    }

    @Override
    public DeviceInfo findDeviceByRisk(RiskRecord riskRecord) {
        return deviceInfoDao.findBySerialNumber(riskRecord.getDeviceSerial());
    }

    @Override
    public void addHandleInfo(int riskId, int userId, int type, String msg) {
        RiskTreatment t = new RiskTreatment();
        t.setCreatedTime(LocalDateTime.now());
        t.setType(type);
        t.setInfo(msg);
        t.setRecordId(riskId);
        t.setUserId(userId);
        riskHandleDao.save(t);
    }

    @Override
    public int countByDept(int deptId) {
        return riskRecordDao.findCountInDept(deptId);
    }

    @Override
    public RiskRecord findLatestRecordByDevice(int id) {
        DeviceInfo deviceInfo = deviceInfoDao.findById(id).orElse(null);
        assert deviceInfo != null;
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        PageRequest pageRequest = PageRequest.of(0, 1, sort);

        RiskRecord riskRecord = new RiskRecord();
        riskRecord.setDeviceSerial(deviceInfo.getSerialNumber());
        Example<RiskRecord> example = Example.of(riskRecord);
        Page<RiskRecord> latestData = riskRecordDao.findAll(example, pageRequest);
        return latestData.stream().findFirst().orElse(null);
    }

    @Override
    public RiskRecord findByEventId(String eventId) {
        RiskRecord riskRecord = new RiskRecord();
        riskRecord.setEventId(eventId);
        Example<RiskRecord> example = Example.of(riskRecord);
        List<RiskRecord> riskRecordList = riskRecordDao.findAll(example);
        if (riskRecordList.isEmpty()) return null;
        return riskRecordList.get(0);
    }

    @Override
    public List<RiskRecordDto> convertRiskRecordDto(List<Object[]> raws) {
        return raws.stream()
                .map(RiskRecordDto::new)
                .collect(Collectors.toList());
    }

    @Override
    public Page<Object[]> findRisk(RiskSearchVo searchVo, Pageable pageable) {
        Integer star = null;
        if (searchVo.getStar() != null) {
            star = searchVo.getStar() ? 1 : 0;
        }
        return riskRecordDao.findRisk(null, searchVo.getDeptId(), searchVo.getDeviceName(), searchVo.getDeviceSerialNumber(), star, searchVo.getRiskType(), searchVo.getRiskLevel(), pageable);
    }


}